package com.wondersgroup.tjfx.redis.executor;

import java.util.List;
import java.util.concurrent.TimeUnit;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.dao.DataAccessException;
import org.springframework.data.redis.connection.RedisConnection;
import org.springframework.data.redis.core.RedisCallback;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.serializer.RedisSerializer;
import org.springframework.stereotype.Component;

import com.alibaba.fastjson.JSON;

@Component
public class RedisBaseExecutor {

	@Autowired
	RedisTemplate<String, String> redisTemplate;

	public boolean set(final String key, final String value) {
		RedisCallback<Boolean> redisCallback = setRcb(key, value);
		return redisTemplate.execute(redisCallback);
	}

	public String get(final String key) {
		RedisCallback<String> redisCallback = getRcb(key);
		String result = redisTemplate.execute(redisCallback);
		return result;
	}

	public boolean expire(final String key, long expire) {
		return redisTemplate.expire(key, expire, TimeUnit.SECONDS);
	}

	public <T> boolean setList(String key, List<T> list) {
		String value = JSON.toJSONString(list);
		return set(key, value);
	}

	public <T> List<T> getList(String key, Class<T> clz) {
		String json = get(key);
		if (json != null) {
			List<T> list = JSON.parseArray(json, clz);
			return list;
		}
		return null;
	}

	public long lpush(final String key, Object obj) {
		final String value = JSON.toJSONString(obj);
		RedisCallback<Long> redisCallback = lpushRcb(key, value);
		long result = redisTemplate.execute(redisCallback);
		return result;
	}

	public long rpush(final String key, Object obj) {
		final String value = JSON.toJSONString(obj);
		RedisCallback<Long> redisCallback = rpushRcb(key, value);
		long result = redisTemplate.execute(redisCallback);
		return result;
	}

	public String lpop(final String key) {
		RedisCallback<String> redisCallback = lpopRcb(key);
		String result = redisTemplate.execute(redisCallback);
		return result;
	}

	private RedisCallback<String> getRcb(final String key) {
		return new RedisCallback<String>() {
			@Override
			public String doInRedis(RedisConnection connection) throws DataAccessException {
				RedisSerializer<String> serializer = redisTemplate.getStringSerializer();
				byte[] value = connection.get(serializer.serialize(key));
				return serializer.deserialize(value);
			}
		};
	}

	private RedisCallback<String> lpopRcb(final String key) {
		return new RedisCallback<String>() {
			@Override
			public String doInRedis(RedisConnection connection) throws DataAccessException {
				RedisSerializer<String> serializer = redisTemplate.getStringSerializer();
				byte[] res = connection.lPop(serializer.serialize(key));
				return serializer.deserialize(res);
			}
		};
	}

	private RedisCallback<Boolean> setRcb(final String key, final String value) {
		return new RedisCallback<Boolean>() {
			@Override
			public Boolean doInRedis(RedisConnection connection) throws DataAccessException {
				RedisSerializer<String> serializer = redisTemplate.getStringSerializer();
				connection.set(serializer.serialize(key), serializer.serialize(value));
				return true;
			}
		};
	}

	private RedisCallback<Long> lpushRcb(final String key, final String value) {
		return new RedisCallback<Long>() {
			@Override
			public Long doInRedis(RedisConnection connection) throws DataAccessException {
				RedisSerializer<String> serializer = redisTemplate.getStringSerializer();
				long count = connection.lPush(serializer.serialize(key), serializer.serialize(value));
				return count;
			}
		};
	}

	private RedisCallback<Long> rpushRcb(final String key, final String value) {
		return new RedisCallback<Long>() {
			@Override
			public Long doInRedis(RedisConnection connection) throws DataAccessException {
				RedisSerializer<String> serializer = redisTemplate.getStringSerializer();
				long count = connection.rPush(serializer.serialize(key), serializer.serialize(value));
				return count;
			}
		};
	}

}
